home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PROGRAMM
/
DB_CLIPP
/
0669.ZIP
/
DB3TAW.TXT
< prev
next >
Wrap
Text File
|
1985-11-30
|
47KB
|
1,070 lines
dBASE III notes .001 Thomas A. Wells
146 D Street SE
See BBS @ 321-7441 Washington, DC 20003
for other notes. (202)546-3409
I am providing a weekly series of these notes covering my
experiences as a dBASEIII programmer. I work as a consultant and
presently am spending 40+ hours per week writing programs and managing
databases using primarily dBASEIII.
This week's experience covers an odd occurrence. While
interactively programming along, debugging a command file for
displaying numbers of items, their record numbers and certain fields,
the computer displayed the error message "File is already open". From
my copy of the "PRODUCT USAGE REPORT" from A-T (see below), I found
that this message should apply only if I tried to use a command file
(.PRG) to call itself, which I wasn't!
There followed an hour of trying to decide what was wrong,
changing EXIT statement locations in various DO WHILE loops both in the
main and sub-programs, and trying to figure out why the call had worked
twice immediately before the error message appeared, etc. Finally it
was time to call the A-T help line - (213)558-0086 (have your dBASE III
serial number handy!).
After some "Have you tried..." and "Yes, I have, but what
about..." iterations, I was told to boot up the backup copy of the .EXE
programs. Since I'm using a PC-XT, I put the disk in drive A, typed
A:DBASE and lo! Everything worked! The final fix for the problem was
to recopy the .EXE programs back to the hard disk from the original
system disk with COPY *.EXE C:.
Why did this work? I'm not sure, but it appears that the copy of
the programs on the hard disk became corrupted, possibly in the stack
management area. So far, after another week's run, no further problems
have occurred. I'm not suggesting this as a fix for all programming
problems, but if you're sure(?) of everything else, give it a try. The
experience leaves me a little less sure of the integrity of either
dBASEIII or IBM's hard disk. My backups have been more frequent
lately.
The PRODUCT USAGE REPORT mentioned above has been very helpful.
I was sent it on request through the Technical Assistance phone number
listed above.
The last 10 pages or so list all the dBASEIII error messages and
their meanings - very helpful to the programmer and, of course, left
out of the original manual. The first half of the document consists of
further tips, elucidations and comments regarding installation,
programming usage of the various commands, and sections on the
dCONVERT and dFORMAT utilities. I don't know whether the report is to
be issued monthly or what - mine is dated October 1, 1984. If you're
seriously programming with dBASEIII, get one!
As a final thought for this week, using Wordstar with the program
has been easy and helpful. Linking the two programs requires nothing
more than creating a CONFIG.DB file with the statements WP=WS and
TEDIT=WS in it. Be sure and run the Wordstar INSTALL program on the
version you want to use before you do, so it will come up running in
the non-document mode (menu E, letter C does the trick).
- - - - -
dBASE III notes .002
When adding records to a file, I sometimes like to stop and press
F4, the function key that is programmed as "dir;". This gives a
listing of the .DBF files only from within dBASEIII. The first time I
did this, the file I just added a record to did not show the additional
record! That is, the number of records was 89 prior to adding one and
still showed 89 after the DIR command.
The answer is relatively simple -- the directory does not appear
to be updated as records are added -- a command to close the file seems
to be required first, such as CLEAR ALL or CLOSE DATABASES. To see how
many records have been added, issue the command CLEAR ALL (or
equivalent), then DIR.
Of course, there are many other ways to determine how many records
a file has while in dBASEIII -- also true of nearly every way of doing
almost anything. One could type GO BOTTOM, then ?RECNO(). Or if you
had just added a record, ?RECNO() would work with out the GO BOTTOM.
This week's puzzler happened while trying to index a .DBF file
where the first index key was a string (character) variable, and the
second key was a numeric variable. According to the rules, the numeric
variable must be converted to a string via the STR() function, since
multiple indexing keys must all be strings. So I did the conversion.
Right in the INDEX command:
INDEX ON string_var + STR(numeric_var) TO indexfile
The result was puzzling, to say the least. Examination of the file
using the EDIT command showed it to be in ascending order, as
advertised, with respect to the string_var, but in descending order
with respect to the numeric_var! Not what I wanted at all.
The conversion to a string should not have affected order of the
sort, since the numeric_var was less than 10 (single digit), and the
string representation appeared to have the same number of leading
blanks for each number. Also, the ASCII value of "2" is higher than
that for "1", so the blanks should not have upset the order.
The cure? Change the field definition to "character". Then, the
indexing command becomes:
INDEX ON string_var1 + string_var2 TO indexfile
Examination of the ordering of the file then showed it to be organized
in ascending order with respect to both keys.
- - - - -
dBASEIII notes .003
This week's dBASE III tip is for the CONFIG.DB file with thoughts
about making screen displays easier to read and maybe a little fancier
with bold, underline and graphics.
CONFIG.DB...
is a file that dBASEIII looks for after you type "DBASE". It may
be used for many different purposes including tieing in a word
processor other than the built-in one, setting most of the SET
parameters and setting the function keys.
Let's see how it is used to set the function keys. First, note
that once again the manual (p. 1-126) is incorrect. There, we are told
to include statements like: F2 = 'CLEAR;' to set the function keys.
Not so! If you try this, an error message will greet you, and the key
will not be set.
The method used to set the function keys is: F2 = CLEAR;
Notice that no quotation marks are used.
Although it is not mentioned, there is a limit to the number of
characters that a function key can represent. I don't know exactly
what it is, but if you try to set one key to:
F2 = SET PRINT OFF; SET DEVICE TO SCREEN;
you will find that the letters at the end, say, "EEN;", have "wrapped"
onto F3. To make the above workable, use the following statement:
F2 = SET PRIN OFF;SET DEVI TO SCREE;
Note the use of the 4-letter abbreviations for the commands, and that
no blank is used after the first ";". Here's an example of a CONFIG.DB
file using the above information:
WP = WSN
TEDIT = WSN
F2 = clea all;
F3 = modi comm
F4 = set prin off;set devi to scre;
As described in an earlier note, the first two statements link
WORDSTAR (INSTALLed in the non-document mode) to the MEMO field editing
and the MODIFY command editing. The last three statements set the
function keys as described above.
The only invisible trick is that for the F3 key there is a blank
after the word "comm " so that all I need to do after pressing the F3
key is to type the name of the command file I wish to edit and press
enter.
The possibilities for using this feature are limited only by the
programmer's imagination. If you use this feature for the final end-
user program remember that you're really trying to make life simpler
for them.
GRAPHICS...
are not too hard to do with dBASEIII. It will, however, take some
patience and trial-and-error...
My system is a PC-XT with the Hercules graphics board and the IBM
mono monitor. I say this because the results of the statements
outlined below will surely be different if you use other hardware.
It all started with a desire to make a full screen look better,
and also to make the important items stand out.
First, DFORMAT was used to draw nice boxes on the screens where
they would help make things clearer. Using DFORMAT, if anyone's
interested, could be the subject of some entire later notes - it's
truly an arcane challenge!
After the boxes were drawn, and the .FMT file was generated, I
naturally wanted to change something. Go back to DFORMAT? No way. It
might be made to edit an existing file, but I'm over 40 and may not
have enough time left to figure out how. So how to make changes to the
graphics?
All the ASCII equivalent characters from the BASIC manual - that's
how! dBASEIII will happily put any character on the screen that is on
that list, so there is a copy of it hanging on the wall next to my
computer. To put a segment of a vertical double line on the screen,
just enter: ? CHR(186) And there it is. Of course, @ SAY may also
be used.
BOLDFACE and UNDERLINE...
are somewhat more involved, but easy once you get the idea. If
the SET COLOR command is properly used for your hardware, all kinds of
emphasis is possible. For you color monitor users, more experimenting
will be needed. The challenge with a color monitor is not to overdo it.
Here's the trick. For my hardware (above) typing:
SET COLOR TO U1/0,0/7,0
results in everything being underlined. Note that the second parameter
0/7 leaves the @ SAY/GET reversed fields alone. Read the manual to see
what is affected by each quantity between the parentheses - it's not
ALWAYS wrong.
Well there is one thing wrong - or at least it "works funny" for
me. The underline is supposed to be turned on by the "U". On my
computer, the "1" turns on the underline - the "U" can be omitted.
To see how this can be put to use in a command file, here's one
way to do it. Build a .MEM file by setting the values of "b", "bu",
"u" and "off" as shown:
Variable Value
u "SET COLOR TO U1/0,0/7,0"
off "SET COLOR TO 7/0,0/7,0"
bu "SET COLOR TO +1/0,0/7,0"
b "SET COLOR TO +7/0,0/7,0"
After setting the values shown, type [SAVE TO color] [enter].
Then later in a command file use the RESTORE FROM color statement to
activate the variables in memory. Don't forget the ADDITIVE modifier
if other variables are active.
"off" represents the default settings; I think they're same as
when dBASEIII is first started.
"u" produces underline, "bu" produces both boldface and underline,
and "b" produces boldface - all on the screen of course.
Then in a command file, or even from the dot prompt, type [&b]
[enter] and everything from then 'til the [&off] occurs will be in
boldface.
The underline is slightly different. If you type [&u] [enter],
every line on the screen will suddenly be underlined! Don't worry -
if the command is issued in a printed line somewhere, it'll only
underline where you tell it to.
- - - - -
dBASE III notes .004 December 19, 1984
This week - a newsflash, a correction and a print hint:
NEWSFLASH
Yesterday an update announcement from A-T arrived. The offer was
to upgrade to dBASE III version 1.1! The details are that for $25 you
get the "improved" version which will run on the PC-AT as well as the
PC & XT, and can be "completely installed on any hard-disk IBM PC/XT,
AT or 100% IBM PC compatible system". The brochure is understandably
silent as to whether or not any of the bugs found by users and/or
mentioned in their "Product Usage Re port" were fixed. My check is in
the mail.
My reaction to this is that since the program has been on the
market less than 6 months, a charge for an update is an insult. Is
this tactic of charging for each item separately an imitation of
IBM? (If the bugs are reduced, maybe it'll be worth it. How about
buyers who get version 1.0 this week? Will they get a "free" upgrade?
If you know anyone about to invest in dBASE III, make sure they get the
word. Surely all the present store stock hasn't been revised to
version 1.1 yet.)
CORRECTION
Last note said there is no stated limit on the length of the SET
FUNCTION command. My face is red - right there on page 4-113 of the
manual it says 30 characters.
PRINT HINT
In formatting printouts to either/both the screen and printer it
is useful to be able to embed a number inside text. For example, you
may want to print: "There are 12 items in this list."
In printing them or using @ SAY, the numbers will be preceded
by up to 7 blank spaces. In the above example if we issued these
commands:
? "There are"
?? n
?? "items in this list."
The result would be: There are 12items in this list.
Note that there are 6 blanks in front of the number and none after
it. There doesn't appear to be any simple way to eliminate the extra
blanks in front of the number. Adding one to the end is simple. If
you know how long the number will be, say always 2 digits, the answer
is simple. Just convert the number to a string and use the STR()
function to print only the rightmost 2 characters. But what if the
number of digits varies? Here is one way to handle that problem:
? "There are "
?? STR(n,(LOG(n+.5)/LOG(10)+1))
?? " items in this list."
Since there doesn't seem to be any easy way within dBASE III to tell
how many digits a number has, the formula above takes your number, n,
and uses the LOG() function to do the job, then the STR() function to
print the exact number you wanted.
The addition of the .5 to the number n is to overcome any internal
inaccuracies in the LOG() function's number representation. The result
then is: There are 12 items in this list.
- - - - -
dBASE III notes .005 January 15, 1984
This note deals with "!", "@" and "?". "!" is a very handy tool
for the dBASE III programmer. It runs any system level program for you
from within dBASE either from the dot prompt or from within a command
file. It can be found in the manual under the equivalent syntax of
"RUN".
For example, I got tired of typing COPY *.dbf a:, etc. at the end
of every session to back up all the files that may have changed, and
besides that, the end user won't want to or maybe even won't know how
to. So here's a backup routine that will back up all the files, with a
built-in safety factor. If the operator puts in the wrong disk, an
opportunity is given to swap it through the use of the FILE command.
Here it is:
*********************** BACKUP.PRG **************************
* Backs up .DBF, .MEM and .NDX files for the operator. *
* An "invisible command" accessed by pressing "P" is *
* included to back up .PRG and .FMT files. This program *
* checks to see whether the proper disk is put in drive A *
* and gives a chance to abort before the copying begins. *
*************************************************************
CLEAR ALL
CLEAR
SET TALK OFF
@ 10,10 SAY "Insert the backup disk into Drive A."
@ 12,10 SAY 'Press "B" to begin, "A" to abort'
WAIT SPACE(21) to j
j = UPPER(j)
* Turn the VERIFY function of DOS ON
! VERIFY ON
DO CASE j
CASE j = "B"
* Check to see if correct backup disk is in drive A:
IF FILE ("A:filename.DBF")
SET CONSOLE OFF
* Copy all the database & related files
!COPY *.DBF A:
!COPY *.MEM A:
!COPY *.NDX A:
SET CONSOLE ON
ELSE
* Argue if the disk isn't recognized...
@ 12,10 CLEAR
* Turn the bright letters on (see earlier note)
&b
@ 12,10 SAY 'This disk may not be the correct one!'
&off
@ 14,10 SAY 'When the correct one is inserted, press "B"'
@ 16,10 SAY 'To Abort, press "A"'
WAIT SPACE(31) TO b
b = UPPER(b)
DO CASE b
CASE b = "B"
SET CONSOLE OFF
!COPY *.DBF A:
!COPY *.MEM A:
!COPY *.NDX A:
SET CONSOLE ON
CASE b = "A"
RETURN
ENDCASE b
CASE j = "A"
RETURN
* This choice backs up the program and format files
CASE j = "P" .AND. FILE('A:filename.PRG')
!COPY *.PRG A:
!COPY *.FMT A:
ENDCASE j
SET TALK ON
SET CONSOLE ON
!VERIFY OFF
RETURN
If your program files or database files are changed often, this
program saves a lot of work. The other possibilities for using "!" (or
"RUN", if you must) are intriguing. How about a communications program
or another DOS function or ... ?
"@" and "?" can both be used to print reports, among other things.
"?" is preceded by a linefeed and a carriage return <CR>, while
"??" is not. Together these two can be used to print many parts of any
report, such as headings.
Where formatted fields such as telephone numbers, dates or dollar
amounts are to be printed, the PICTURE clause is handy, and "@" is
probably easier to use.
To have the output of both "?" and "@" routed to the printer, it
is probably safer to use:
SET PRINT ON
SET DEVICE TO PRINT
Then anything that either "@ SAY" or "?" does is done by the printer
and not the console screen. "@ GET" is ignored.
Watch out for putting the "@" commands into a sequence that causes
the printer to back up either a line or space(s) on a line. You may
get an unwanted EJECT by the printer. Here's an example of the use of
a mixture of these commands:
* Printer codes
bold_on = CHR(27) + CHR(88) + CHR(49)
bold_off = CHR(27) + CHR(88) + CHR(48)
? bold_on
?? heading
?? SPACE(20) + DTOC(DATE())
?
? bold_off
@ PROW(),0 SAY id_number PICTURE "@R 99-(999)-99"
@ PROW(),PCOL()+2 SAY id_number_2 PICTURE "@R 99/999/A"
@ PROW(),PCOL()+2 SAY SUBSTR(var1,1,14)
@ PROW(),PCOL()+2 SAY var2 + ". " + var3
@ PROW(),PCOL()+2 SAY SUBSTR(var4,1,1) + ". " + var5
@ PROW(),PCOL() SAY RECNO()
?
In the example the variables bold_on and bold_off are printer
control codes covered in an earlier note, if memory serves. PROW()
keeps the cursor on the same line. PCOL()+n spaces the data to match
the heading. Either "?" or "@" could have been used to print var1 -
var5 and RECNO(). The final "?" is to move the cursor to the beginning
of the next line. Without it, any subsequent output will start at the
end of RECNO(). Instead of PCOL() +n, a number may be used to select
the starting column for the next item. @ PROW(),100 will place the
first character in column 100 (just be sure your printer can
accommodate column 100). Place your collection of "?" and "@"
statements inside one or more DO WHILE loops and you're set to go.
- - - - -
dBASE III notes .006 January 24, 1984
Version 1.1 has arrived. Comments this time are about v1.1:
Installation, Autostart, dFORMAT/SED, and "Oops".
INSTALLATION
Installation looks difficult, but is easy. The trick is to follow
the directions. The bottom line is that yet another protection scheme
is used, this time to allow hard disk users to boot directly from the
hard disk without the system disk having to be in drive A:. To unravel
the directions, you are apparently allowed one copy on the hard disk
per system disk. The intent is that if you want to move the software
to another machine you must "uninstall" the copy (put it back onto the
system disk), then move the program to your other machine. Ridiculous.
Even more ridiculous is A-T's statement that you may want to
"uninstall" the program if "your hard disk becomes damaged"! They
don't tell how to do this wonderful magic feat.
I'm opposed to copy protection. There are already several small
programs available for unprotecting dBASE III v1.0; those for v1.1
will be soon.
AUTOSTART
It is now practical (and legal) to boot your database from the
hard disk using a combination of the AUTOEXEC.BAT and CONFIG. DB files.
Here's how. The AUTOEXEC.BAT file has as its last two statements:
CD\DBMS\DB3
dbase
The first statement changes the default directory to the dBASE III
directory and the last invokes the program. Since v1.1 requires no
boot disk in drive A:, it comes alive and looks for a CONFIG.DB file.
Mine ends with:
COMMAND = DO mainmenu
The result of these two additions to these files means that I can walk
up to the computer, flip on the main switch and walk away. In about
two minutes (using a 640K XT), the main menu is on the screen waiting
for my use without ever pressing a key. See page 1-126 in the manual
for a little more about CONFIG.DB and an example of COMMAND.
dFORMAT/SED
What was dFORMAT in v1.0 is SED in v1.1. The new version looks
the same as the old, but it's a different size so maybe some of the
bugs have been fixed. I liked dFORMAT so I plan to like SED. It is a
good time-saver for creating screens for input and output. You can
even use fancy boxes! Try it - the on-line help is good.
OOPS
After one day with v1.1, a bug appeared. Or maybe I should call
it a correction to the bug. With v1.0, printing a date to the screen
with @ SAY required a PICTURE clause like "@R 99/99/ 99" to get it to
look like a date. On the printer, you didn't need it, which agreed
with the manual (see page 4-20). That was one page that never made
itself clear to me, except it encouraged me into some trial/error that
resulted in my not using any PICTURE clauses with date variables
except, as noted above, on the screen. If you happen to have a good
explanation of page 4-20, please send it right away.
Now v1.1 works the same as the printer. No PICTURE clauses needed
on the screen. Is that clear from the documentation? No.
Documentation for v1.1? Here's the total:
Installation - 5 pages
Corrections - 4 pages (scattered items)
New pages - 1
SED comments - 4
It might be a good idea to funnel all the new and/or old bugs for
dBASE III, particularly v1.1, to one person. The idea is to accumulate
them and forward to users groups and A-T.
- - - - -
dBASE III notes .007 April 4, 1985
Today's a good day for some thoughts about screen and printer
graphics. I use Wordstar for all my dBASE III programming. As a
result, graphics are fairly simple to do, as I hope you'll see shortly.
If you use Sidekick, or the dBASE III editor, or some other word
processor the principles may or may not apply.
The first problem is to get the graphics characters into the
editor; that is, to make them available on the screen. I did it by
using dFORMAT, supplied with v1.0. The "new" screen-making tool, SED,
supplied with v1.1 will make you work harder for the same result. Or
less. The process for getting control of lines and boxes is:
1. Draw a box any way you can in either SED or dFORMAT.
(Or any other way - all's fair.)
2. Use SED or dFORMAT to generate the .PRG file.
(Or see above parentheses)
3. Import the .PRG file into your word processor.
4. Use your word processor's functions for copying, moving
and editing to construct other figures as needed.
If you have dFORMAT, you can generate a box completely and import
the whole thing into your word processor. If you're "stuck" with SED,
it's a little more arcane.
Here's a short list of keys and their effect on the screen for
those with SED:
Key CHR() Key CHR()
F1 187 F2 200
F3 189 F4 190
F5 191 F6 192
And so on. Refer to your BASIC manual for the figures represented by
the ASCII codes.
With SED, if you use the SHIFT, ALT and CONTROL keys with the
function keys (and even the backslash key) you can get some of the PC
graphics & other special characters, but it's almost too time
consuming. Besides, after all that I still wasn't able to make a
complete box! The vertical line character managed to escape me
completely. So I went back to dFORMAT, got both the single and double
line samples, and started from there.
As another possibility, I used Wordstar in the non-document mode
to write this note, so the example below may be used, if you can ingest
it with your dBASE III editor. Here's a sample box:
@ 2,0 SAY "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"
@ 2,55 SAY "MMMMMMMMMMMMMMMMMMMMMMM;"
@ 3,0 SAY ":"
@ 3,78 SAY ":"
@ 4,0 SAY ":"
@ 4,14 SAY "Whatever the TITLE of this here screen is..."
@ 4,78 SAY ":"
@ 5,0 SAY ":"
@ 5,78 SAY ":"
@ 6,0 SAY ":"
@ 6,78 SAY ":"
@ 7,0 SAY ":"
@ 7,20 SAY "und so weiter..."
@ 7,78 SAY ":"
@ 8,0 SAY ':'
@ 8,78 SAY ":"
@ 9,0 SAY ":"
@ 9,55 SAY ':'
@ 10,0 SAY ":"
@ 10,55 SAY ":"
@ 11,0 SAY ":"
@ 11,55 SAY ":"
@ 12,0 SAY ":"
@ 12,55 SAY ":"
@ 13,0 SAY ":"
@ 13,78 SAY ":"
@ 14,0 SAY ":"
@ 14,55 SAY ":"
@ 15,0 SAY ":"
@ 15,78 SAY ":"
@ 16,0 SAY ":"
@ 16,78 SAY ":"
@ 17,0 SAY ":"
@ 17,78 SAY ":"
@ 18,0 SAY ":"
@ 18,78 SAY ":"
@ 19,0 SAY ":"
@ 19,78 SAY ":"
@ 20,0 SAY ":"
@ 20,78 SAY ":"
@ 21,0 SAY ":"
@ 21,78 SAY ":"
@ 22,0 SAY ":"
@ 22,78 SAY ":"
@ 23,0 SAY "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"
@ 23,55 SAY "MMMMMMMMMMMMMMMMMMMMMMM<"
The above code should, if you insert it in a .PRG or a .FMT file,
produce a complete box on your screen or printer consisting of gen -
yoo - wine PC graphics characters.
If you drag this code (or the whole note) into your word
processor, you may see only colons (:), H's (H), M's (M), semicolons
(;), I's (I) and a less than sign (<). Don't be fooled; this is the
way the graphics are displayed by Wordstar.
Don't erase one of the "graphics" colons and then try to replace
it with a colon from your keyboard - life don't work that way. The
ASCII codes for the "real" colon and the "graphics" colon are quite
different. By about 128...
If you're still here, and have got this figure or an equivalent
one into your word processor, you're ready for step 4. Move, copy and
delete until you (think you) have reformed the size and shape of your
box to suit your need. Then run (DO) the program. Chase the bugs
until you get it right, and spruce up all your screens. As a side
note, you can also "DO" a .FMT file!
Also note that if you have a PC "compatible" printer, both single
and double line graphics will print, though most printers print either
as only a single line.
- - - - -
dBASE III notes .008 April 11, 1985
PEEK...
is not documented, but a dBASE programmer can have some fun with
it and perhaps learn a little about programming and screen handling in
the process. So purists are excused from reading the following example
program:
******** PEEK.PRG
* Prints the location, value & CHR() where possible
* OK up to location 32767 - modify for higher locations
CLEAR
INPUT "begin at ?" to begin
INPUT "how many ?" to num
loc = begin
r = 4
c = 0
DO WHILE loc < begin + num
* trim location number & put in proper location on screen
* see earlier note for trim technique involving logs
@ r,c*25 SAY STR(loc,(LOG(loc+.5)/LOG(10)+1))
pk = PEEK(loc)
* take care of "unprintable" characters
IF pk > 31 .AND. pk <255
@ ROW(),COL() SAY " CHR("+STR(pk,3)+ ") = "+CHR(pk)
ELSE
IF pk <> 0
@ ROW(),COL() SAY " CHR("+STR(pk,3) + ")"
ELSE
@ ROW(),COL() SAY " CHR( 0)"
ENDIF
ENDIF
loc = loc + 1
* print downward on screen
r = r + 1
* don't go off the bottom of the screen
IF r > 22
r = 4
c = c + 1
* don't go off the right of the screen
IF c > 2
c = 0
WAIT
@ 4,0 CLEAR
ENDIF
ENDIF
ENDDO
* don't overwrite data on the screen when finished
@ 23,0 SAY ""
If you trim the above program out of this note and run it, you
will see:
- a request for the locations you want printed on the screen
- a request for the number of locations after the start above
- columns of data printed
The programming techniques used are:
- printing in columns because they're easier to read than rows
- showing the ASCII representation where possible
- managing to stay on the screen, avoiding errors
There are two challenges here I'd like to offer. First, see if
you can make the program work above location 32767. Second, with the
start given, write a disassembler! At least for the memory locations
below 32768; you could use a .dbf to store the op-codes and the
associated decimal & hex values. Silly? Maybe not, if you consider
it a way to learn.
INDEXING...
can be very helpful for quick access to data in any order, and is
necessary for certain other commands such as SEEK, FIND, SET INDEX and
SET RELATION.
Once a file is INDEXed, it is important to back up the .ndx file
whenever the .dbf file is backed up. If you don't back it up, loss of
a disk will mean reconstructing the .ndx file. If you know what the
index key fields were either from experience or documentation then
rebuilding the index file is only time consuming. If you don't know
what the key fields were, your problem could be quite substantial.
One way to avoid the problem is to keep track of the .ndx file
keys. Here's one way to do it:
Back up your .ndx files along with the associated .dbf files.
A suggested "easy" way to do this is contained in an earlier note.
Then keep printed copies of your file structures handy by issuing
the command "LIST STRUCTURE TO PRINT" every time you modify the file's
structure. Then after each time you create an index file for the .dbf
file, type "USE filename INDEX indexname" then press F6 (DISPLAY
STATUS) to show the file in use. Note that the .ndx file's name and
key fields are also shown. Do a screen print or "DISPLAY STATUS TO
PRINT" and tape the index file info to the printout of the .dbf file
structure. This process is actually quite easy.
Remember to back up any related .mem and .dbt files along with the
above. To quote Macpherson's Law: "Murphy's Law is too optimistic.".
- - - - -
dBASE III notes .009 April 30, 1985
This week's note concerns the "&" and the "*"
& is the dBASE MACRO FUNCTION. It looks like an ampersand (because
it is!) and works in ways that new dBASE programmers sometimes have a
lot of trouble figuring out. First try the program below. It's short
but it illustrates the use of the "&" and also the asterisk or NOTE
function:
**************** ASTERISK.prg
* demonstrates the "&" and the "*"
****************
a = "*"
? "a" + "&a"
&a ? "This is line 1"
a = ""
&a ? "This is line 2"
If the keyword (NOTE) or the asterisk symbol appears in the first
column of a line, dBASE ignores the rest of the line. Same as the REM
keyword or the apostrophe does in many versions of BASIC. When you run
ASTERISK.prg this is what takes place:
1 - the variable "a" is set equal to an asterisk.
2 - the first print statement prints an "a" and then "the contents
of a". If you think of the "&" symbol as "the contents of" it
may help you see what is taking place. Therefore, since "the
contents of a" is an asterisk, that's what appears on the
screen.
3 - in the next line the first expression is &a. Since the & is
the "contents of " function, the computer looks for its
argument "a", sees it is an asterisk and puts that character
first on the line. Seeing an asterisk first on a line causes
the computer to see the line as a comment and ignore it!
4 - "a" is "nulled out", that is, "a" is set equal to null - the
empty string.
5 - nearly the same line as before except that "a" is no longer
an asterisk but a null, so the "?" or print statement is
executed.
The program's output? Here it is:
do asterisk
a*
This is line 2
.
Try the program with other values for a such as *fGHY67 and 1234.
Expect and interpret different results and error messages. When you
are comfortable with &, use it in other dBASE statements such as:
SET FILTER TO fieldname = "&variable"
LOCATE FOR fieldname = "&variable"
and all those other places that "the contents of" a variable are
needed.
See notes .003 and .005 for examples of other uses of the &
function.
- - - - -
dBASE III notes .010 May 21, 1985
This week's note concerns DO, IF, SUM and "&" macro substitution. It
started innocently with a program as outlined below containing a DO
WHILE and an IF statement, like this:
* FOO.prg
* or how to find a bug in dBASE III v1.1
* Initialize some variables
date = CTOD("01/01/01")
* these are all date field names
f1 = "FIELD1"
f2 = "B->FIELD2"
.
.
.
f28 = "FIELD28"
* open the files
SELECT 1
USE FILENO1
SELECT 2
USE FILENO2
* link the two files by record no. since there are many fields
SELECT 1
SET RELATION TO RECNO() INTO FILENO2
* cause the problems
GO TOP
DO WHILE .NOT. EOF()
IF &f1>date .AND..NOT.(&f23<date.OR.&f24<date.OR.;
........OR.&f28<date)
SUM fieldname TO total FOR &f1>date .AND..NOT.(&f20<date.OR.;
.........&f19<date.OR.&f18<date)
ENDIF
ENDDO
? "Title of the sum = "
?? total
.
.
.
etc
Anyway, I hope you get the idea: an IF statment inside a DO loop, each
with a looooong qualifying clause of the Boolean persuasion.
When I tried to run the program, it executed fine until it hit the
first record to fail the IF test. Then the dot prompt appeared without
any error message and without executing the print statement following
the DO WHILE! It was as though the CANCEL command had been executed,
but at least with CANCEL you get a message like "DO cancelled". So the
debugging began.
First, there is a limit on line length. 254 characters. It was
possible that the expansions caused by the macros might have created a
line longer than 254 characters (true for most command lines in dBASE).
So, shorten the line. Same problem. Less than 254 characters for
sure. Now what?
Second, they admitted that use of a PUBLIC variable in a SUM
statement can cause incorrect summing. So I eliminated all PUBLIC
variables in the program (Well, there were a few things I didn't tell
you, but they didn't make any difference). No improvement.
Then I copy the .prg file to FOO.prg and start eliminating
statements and pieces of statements, a debugging technique I use when
everything else has failed.
The first thing out was one of the macro substitutions in the SUM
statement. The program ran perfectly. Flushed with success, I made
the same change to the original program. It failed.
I went back to foo, put the macro back into the SUM statement and
it ran perfectly!
Checked the file for corrupted data. Everything fine.
It still bothered me that with TALK ON, the IF statement was the
last line executed before the message-free exit from the program
occurred. I reexamined the program logic and decided I could do the
job perfectly well without the IF or DO statements by suitably
modifying the SUM statement. All the macro substitutions went into a
large SUM statement. I got the answers about the data I needed for the
report and had no more unexpected halts occur in the program.
About all I can conclude from this exercise is that there IS a bug
which allows dBASE to exit a loop - back to the dot prompt - without
any hint as to why. I also confess to ignorance. Anyway, if you
happen across anything like this, call or write.
As to another similar occurrence with v1.0, that is, mysterious
and inconclusive, see one of my earlier notes.
- - - - -
dBASE III notes .011 May 23, 1985
This week's note concerns INDEX, $ and debugging.
INDEX...
is the slickest way to make a file appear as though it was sorted
even if it was not. Using:
INDEX ON fieldname list TO indexfilename
is a neat, fast way to organize data items to reduce print time or the
time to recall or add data to a file. One of the problems appears in
the latter area. Let's use a fictitious example program to illustrate.
First suppose you have created the file FOO.dbf containing the
imaginative fieldnames of FIELD1, FIELD2, ... FIELD30. Then you have
entered data and now issue the command:
INDEX ON FIELD1 + FIELD3 + FIELD22 TO FOO
This statement creates the index file known as FOO.ndx which, when in
use, makes the file appear sorted on the key FIELD1 and then the sub-
keys FIELD3 and FIELD22. For example, if FIELD1 is the State and
FIELD3 is the City, then the data will appear in State order and within
each group of States it will appear sorted on the City, etc.
From here on whenever you USE FOO, it will appear in the order you
entered the data. If you USE FOO INDEX FOO, when you EDIT, SKIP or
otherwise step through the file the data will appear as though it was
sorted on the three "key fields" above: FIELD1, FIELD3 and FIELD22.
How do you keep the index file updated and if you add data to any
of the KEY fields (1, 3 or 22 above), when will the index file be
updated? As usual in programming, there isn't one simple answer. Here
are some ways - maybe you can think of others:
1. USE FOO
...add/edit data...
SET INDEX TO FOO
REINDEX
2. USE FOO INDEX FOO
add data..
(reindexing automatically done)
In short, if you update while the index is not in use, you will need to
REINDEX afterward, while using the index file. If the index file is in
use, it is automatically updated.
So far so good. How about creating another index file for
FOO.dbf? Let's say you do this:
USE FOO
INDEX ON FIELD17 + FIELD2 TO FOO2
Now you've got two index files for the same data file - FOO.ndx and
FOO2.ndx. How can these both be updated quickly? If you try it,
REINDEX can be slow, especially if the number of key fields is large.
A quicker way is to use one of the SET commands:
USE FOO
SET INDEX TO FOO2, FOO
This statement makes the file appear as though it is sorted on the keys
in FOO2. FOO is along for the ride in that regard (read: doesn't do
anything but is in use), but it is now also updated automatically
whenever any of its key fields are changed. No reindexing needed.
One caveat: be sure to pay attention to the manual's remarks about
mass updates to key fields. If you do it wrong, you can lose large
chunks of data!
Read the section in the manual about SET while you're at it.
There are quite a few handy items there, not only for indexing but
also for relating one file to another either by record number or key
field, setting printer margin, paths and so on...
$...
is the substring search function. The only reason I mention it
here is due to an old habit of naming string or dollar amount variables
with the "$" character somewhere in the name. Such as graph$, amount$
or similar. Well this old habit started when I was learning BASIC and
dies hard.
Interestingly, filenames like fn$ and the like work fine. So do
the variable names like amount$. When I tried to get a little fancier
and wrote "app$tot" as a variable name, I got caught. I've forgotten
the specific error message, but you'll recognize it if you see it. In
short watch out for using special characters in your variable names.
If you use "&" in one, you won't get any sympathy from me at all.
DEBUGGING...
is an art as well as a science. It is estimated to take about 20%
or more of the time involved in writing a well-planned program where
the planning takes 50% of the time. For those who like to "sit down at
the piano and play" with only an overall idea of the objectives of the
software, debugging percentages can approach 100%.
Some useful techniques to use are TALK, STEP, PUBLIC, CANCEL,
DEBUG and ECHO. Here is a short look at how each might be used:
SET TALK ON
is probably the most generally useful technique. When issued as a
command in the .prg file (or from the dot prompt if the .prg file
doesn't SET TALK OFF and cancel that command), you can see the result
of each line of the program printed on the screen (or the printer if
you have SET PRINT ON). If a value of a variable is changed, it will
be printed.
When the error you are looking for occurs, you can tell which line
is being executed (usually) and what the values of the most recently
set variables are. Often, the value causing the problem may be set in
another line somewhere earlier.
PUBLIC...
can be used to examine the variable values if the error you are
chasing causes the program to stop and the dot prompt to appear, or if
you press Escape. If you then press F7 (display memory), and none of
the variables have been declared public, no values will appear. So to
use PUBLIC, put the statement at the beginning of your command file
like this:
PUBLIC variable list
and then F7 will give you their latest values. One caution about this
technique: if your bug is in a SUM statement, find another way to
debug! As noted in the previous note (#10), PUBLIC and SUM may not get
along too well together.
STEP...
will allow the program to be executed one line at a time. If you
need to stop the program after each line:
SET STEP ON
will do it. You'll be asked to press a key after each line of the
program has executed. Useful for errors that can't be pinpointed to
a particular line if the program isn't printing or if it's going too
fast through a segment of the code for you to stop it easily. Issue
the command either from within a program if you don't want the thing
to ask you to press enter for every step before a certain point, or
from the dot prompt if you do.
CANCEL...
will stop the program and put you back to the dot prompt from any
place within a command file. It acts like a breakpoint in an assembly
language program by letting you choose where to stop execution. If you
use PUBLIC in the same program, the values of the variables will then
be available at that line for you to examine.
ECHO...
is a little like TALK, except where TALK displays the values of
any variables that change, ECHO displays (or prints) the command(s)
that are executed.
DEBUG...
is handy for directing the output of the ECHO command to the
printer instead of the screen if you want to keep the screen from being
cluttered or overwritten while you are debugging.
All of the above SET commands are described in the manual,
sometimes even in more detail.
The above hints are really only tools for debugging provided in
the dBASE III programming language. The most important one is located
between your ears.
In the above debugging comments, various ways of employing these
tools were mentioned. Now let's take a look at a few circumstances
where you might want them.
After you have planned and written a program, the next step will
be to execute it. Print reports, add data, enter data or make
calculations, for example. This is the sequence:
1. Plan the program logic
2. Break the logic into steps of smaller size.
3. Do step 2 until each step is (almost) a small enough segment
to be coded directly from the logic.
4. Write the code.
5. Execute the code.
6. Debug the code.
Steps 1-3 usually take 50% of the programming time. Step 4 can
then be done in about 10% of the time. Step 6 consists of several
discrete kinds of operations:
1. Syntax error checking.
2. Running test data.
3. Logic error checking.
SYNTAX ERRORS...
are usually the simplest kind of errors to correct. In most
cases, the program will halt and an error message is printed. For most
errors in dBASE III, a question mark will appear just to the right of
the actual error. Then you correct the error and run again. Until
there aren't any more syntax error messages. You might think that is
that. Well, as you have by now guessed, there's a lot more.
There are some errors that could be considered either syntax or
logic errors that won't give you any message. For example, if you open
file FOO in area 1 and GOO in area 2 and then try to GET FIELD2 from
area 1 while you are in area 2. You forgot that you were in the wrong
area and should have written GET A->FIELD2. In this case, the screen
position where the result of the GET should have displayed will be
blank. It is easy to think "there wasn't anything in the field in that
record, so the blank is OK". The blank is NOT OK - it's an error.
Thus you want to develop the habit of (at least mentally)
questioning every item that is printed by your code. A blank may or
may not really be a blank...
RUN TEST DATA...
The next important step in debugging is to run some test data.
Make sure you know in advance what the output will be. Try to run data
at both ends and the middle of your data range. For example, if your
program accepts data between $40 and $4 million for a variable value,
use both of these and several intermediate ones even if the usage of
the extremes is rare. Then check the results by hand.
LOGIC ERRORS...
may be much easier to spot if you run test data. Wrong answers
may show them (or may show errors in your hand calculations) much more
efficiently than having your boss question them later at an inopportune
moment. Other logic errors may show up in printing. Usually obviously.
The sneakier kind are those that may show up in selection logic, for
example:
COUNT FOR YEAR(FIELD3)>0.AND.FIELD16<56.OR.FIELD2<variable TO a
Here the Boolean logic should be assembled correctly so that "what you
THOUGHT you told the computer to do IS ACTUALLY what you told the
computer to do".
Parentheses would make the above COUNT statement clearer or change
its meaning entirely.